﻿<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title></title>
    <link rel="stylesheet" href="content/css/ko.css" />
    <style type="text/css">
    

        td {
            border: dotted 1px;
            min-width: 4px;
        }

        .clickable {
            cursor: pointer;
        }



        .match {
            border: dotted 1px;
            display: table-cell;
            display: inline-block;
            min-width: 10px;
            text-align: center;
        }

        .selected {
            color: blue;
        }

        .matches {
            max-width: 400px;
        }

        .matches, .solved {
            border: solid 1px;
            margin-bottom: 2px;
            min-height: 1.5em;
        }

        .matched {
            color: darkgreen;
        }

       
    </style>
</head>
<body>
    <div class="sticker floatLeft">
        <div class="stickerHeading">
            <h1>Memory board</h1>
        </div>
        <div class="matches" data-bind="foreach: matches">
            <div class="match" data-bind="text: $root.selection()!==$data && $root.selection2() !==$data ? $root.placeholder : value, click: $root.select, css: {matched: solved,clickable: !(solved()),selected:$root.selection()===$data || $root.selection2()===$data }"></div>
        </div>

    </div>
    <div class="sticker floatLeft">
        <div class="stickerHeading">
            <h1>Solved board</h1>
        </div>
        <div class="solved" data-bind="foreach: {data:solved,afterAdd: onAdd,beforeRemove: onRemove}">
            <div class="match" data-bind="text:value"></div>
        </div>

    </div>
    <div class="sticker liveExample">
        <div>
            unselected placeholder:
        <input type="text" data-bind="value:userplaceholder" />
        </div>
        <button data-bind="click:reset">reset</button>
    </div>
    <div class="sticker liveExample">
        <input type="checkbox" data-bind="checked: removeSolved" /><span>Remove solved matches</span>
        <div class="matchablescontainer">
            <span>items:</span>
            <div class="matchables" data-bind="foreach: {data:matchables,beforeRemove: onRemove, afterAdd: onAdd}">
                <div class="matchable">
                    <input type="text" data-bind="value: writer" /><span class="clickable" data-bind="click: $root.removeMatchable"> x </span>
                </div>
            </div>
            <div><span class="clickable" data-bind="click: addMatchable">Add new item</span></div>
        </div>
    </div>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/2.2.1/knockout-min.js"></script>

    <!--<script src="http://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.10.0/jquery-ui.min.js"></script>-->
    <script>

        //http://sroucheray.org/blog/2009/11/array-sort-should-not-be-used-to-shuffle-an-array/
        Array.prototype.shuffle = function () {
            var i = this.length, j, temp;
            if (i == 0) return;
            while (--i) {
                j = Math.floor(Math.random() * (i + 1));
                temp = this[i];
                this[i] = this[j];
                this[j] = temp;
            }
        };

        //https://github.com/SteveSanderson/knockout/issues/416
        ko.observableArray.fn.pushAll = function (valuesToPush) {
            var underlyingArray = this();
            this.valueWillMutate();
            ko.utils.arrayPushAll(underlyingArray, valuesToPush);
            this.valueHasMutated();
            return this;  //optional
        };

        var item = function (val, koPlaceHolder) {
            var self = this;
            self.value = val;
            self.uservalue = val;

            self.display = ko.observable(koPlaceHolder);
            self.solved = ko.observable(false);
            self.writer = ko.computed({
                read: function () {
                    return self.value;


                }, write: function (value) {
                    self.uservalue=value;
                    if (self.uservalue !== undefined && self.uservalue !== '') {
                        self.value = value;
                        if (self.display() != koPlaceHolder())
                            self.display = koPlaceHolder;
                    }
                }
            });

        };

        var memoryModel = function () {
            var self = this;
            self.onAdd = function (node) {
                if (node.nodeType === 1) {
                    $(node).hide().fadeIn('slow');
                }
            };
            self.onRemove = function (node, index, data) {
                if (node.nodeType === 1) {

                    $(node).fadeOut('slow', function () {
                        console.log('removing: ' + data.value);
                        $(this).remove();
                    });
                }
            };
            self.placeholder = ko.observable('X');
            self.userplaceholder = ko.computed({
                read: function () { return self.placeholder(); },
                write: function (value) {
                    if (value !== undefined && (value.match === undefined || !value.match(/^\s*$/)))
                        self.placeholder(value);
                }
            });
            self.matchables = ko.observableArray([new item(0, self.placeholder), new item(1, self.placeholder), new item(2, self.placeholder), new item(3, self.placeholder)]);
            self.removeSolved = ko.observable(true);
            self.removeMatchable = function (matchable) {
                self.matchables.remove(matchable);
            };
            self.addMatchable = function () {
                self.matchables.push(new item(undefined, self.placeholder));
            };
            self.items = ko.observableArray([]);
            self.matches = ko.computed(function () {
                return ko.utils.arrayFilter(self.items(), function (i) {
                    return !(i.value)
                        || i.value === undefined
                        || i.value === ''
                        || (i.value.match && i.value.match(/^\s*$/))
                        || i.solved() !== true
                        || !self.removeSolved();
                });
            });

            self.solved = ko.computed(function () {
                return ko.utils.arrayFilter(self.items(), function (i) {
                    return i.solved() === true;
                });
            });


            //self.rows = ko.computed(function () { return self.matches().slice(); });
            self.selection = ko.observable(null);


            self.selection2 = ko.observable(null);
            self.display = ko.computed(function () {
                var i = ko.dataFor(this);
                if (i === undefined)
                    return i;
                if (self.selection() == i || self.selection2() == i || i.solved())
                    return i.value;
                return self.placeholder();
            });
            self.reset = function () {
                self.items.removeAll();
                ko.utils.arrayForEach(this.matchables(), function (item) {
                    item.solved(false);
                });
                
                self.items(self.matchables().slice(0));//have to clone so the remove all doesn't kill it
                var length = self.items().length;
                for (var i = 0; i < length; i++) {
                    var toClone = self.items()[i].value;
                    self.items.push(new item(toClone, self.placeholder));

                }
                var shuffled = self.items().slice(0);
                shuffled.shuffle();
                self.items.removeAll();
                self.items(shuffled);

                self.selection(null);
                self.selection2(null);
            }

            self.select = function (item) {
                if (item.solved() === true) { return; }

                if (self.selection() == item) {
                    item.display(self.placeholder());
                    self.selection(null);
                } else if (self.selection2() == item) {
                    item.display(self.placeholder());
                    self.selection2(null);
                } else if (self.selection() == null) {
                    item.display(item.value);
                    if (self.selection2() != null && self.selection2().value == item.value) {
                        item.solved(true);
                        self.selection2().solved(true);
                        self.selection2(null);


                    } else {
                        self.selection(item);
                    }
                } else if (self.selection2() == null) {
                    item.display(item.value);
                    if (self.selection().value == item.value) {
                        item.solved(true);
                        self.selection().solved(true);
                        self.selection(null);
                    } else {
                        self.selection2(item);
                    }
                }
            };
            self.reset();
        }
        ko.applyBindings(new memoryModel());
    </script>
</body>
</html>
